#include "gd32f30x.h"
#include "BMP280_Register.h"
#include "FreeRTOS.h"
#include "task.h"
#include "math.h"

#define SCL_Port GPIOB
#define SCL_Pin  GPIO_PIN_14
#define SCL_RCU  RCU_GPIOB
#define SDA_Port GPIOA
#define SDA_Pin  GPIO_PIN_7
#define SDA_RCU  RCU_GPIOA

#define W_SCL(x)		gpio_bit_write(SCL_Port, SCL_Pin, (bit_status)(x))
#define W_SDA(x)		gpio_bit_write(SDA_Port, SDA_Pin, (bit_status)(x))

BMP280_HandleTypeDef bmp280;

#define dig_T1    bmp280.T1
#define dig_T2    bmp280.T2
#define dig_T3    bmp280.T3
#define dig_P1    bmp280.P1
#define dig_P2    bmp280.P2
#define dig_P3    bmp280.P3
#define dig_P4    bmp280.P4
#define dig_P5    bmp280.P5
#define dig_P6    bmp280.P6
#define dig_P7    bmp280.P7
#define dig_P8    bmp280.P8
#define dig_P9    bmp280.P9
#define dig_Tfine bmp280.T_fine


double bmp280_compensate_P_int64(int32_t adc_P);
double bmp280_compensate_T_int32(int32_t adc_T);

void dd(void)//FreeRTOS写的，写之前不好加延时，加之前怎么都找不到错误，加了就正确了，加就是了
{
	uint16_t i = 2000;
	while(i--){}
}
uint8_t R_SDA(void)
{
	dd();
	return gpio_input_bit_get(SDA_Port, SDA_Pin);
}

void bmpIIC_GPIO_Init(void)
{
	rcu_periph_clock_enable(SDA_RCU);
	gpio_init(SDA_Port, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, SDA_Pin);

	rcu_periph_clock_enable(SCL_RCU);
	gpio_init(SCL_Port, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, SCL_Pin);

	gpio_bit_set(SDA_Port, SDA_Pin);
	gpio_bit_set(SCL_Port, SCL_Pin);
}
//在SCl高电平期间，SDA由高电平变为低电平，为起始信号
void IIC_Start(void)
{
	W_SDA(1);
	dd();
	W_SCL(1);
	dd();
	W_SDA(0);
	dd();
	W_SCL(0);
	dd();
}
//在SCL高电平期间，SDA由低电平变为高电平，为停止信号
void IIC_Stop(void)
{
	W_SDA(0);
	dd();
	W_SCL(1);
	dd();
	W_SDA(1);
	dd();
	W_SCL(1);
	dd();
}
void IIC_SendByte(uint8_t Byte)
{
	for(uint8_t i = 0;i < 8; i++)
	{
		//SCL低电平变化SDA，在起始信号中就已经拉低了SCL
		W_SDA(Byte & (0x80 >> i));//先发送高位
		dd();
		W_SCL(1);//拉高SCL让从机读取数据
		dd();
		W_SCL(0);
		dd();
	}
}
uint8_t IIC_ReadByte(void)
{
	uint8_t Ret = 0x00;
	W_SDA(1);
	for(uint8_t i = 0; i < 8; i++)
	{
		W_SCL(1);//SCL高电平读取数据
		dd();
		if(R_SDA() == 1)
		{
			Ret|=(0x80 >> i);
		}
		dd();
		W_SCL(0);//拉低SCL，从机可以发送数据
		dd();
	}
	return Ret;
}
void IIC_SendAck(uint8_t ack)
{
	dd();
	// W_SCL(0);因为之前的读取或则接收数据的操作里面最后都有将SCL线拉低的操作，所以可以不加
	W_SDA(ack);
	dd();
	W_SCL(1);
	dd();
	W_SCL(0);
	dd();
}
uint8_t IIC_ReceiveAck(void)
{
	dd();
	uint8_t rack = 0;
	W_SDA(1);
	dd();
	W_SCL(1);
	dd();
	rack = R_SDA();
	dd();
	W_SCL(0);
	dd();
	return rack;
}
void bmp_write_reg(uint8_t reg, uint8_t data)
{
	IIC_Start();
	IIC_SendByte(BMPADDRES);
	IIC_ReceiveAck();
	IIC_SendByte(reg);
	IIC_ReceiveAck();
	IIC_SendByte(data);
	IIC_ReceiveAck();
	IIC_Stop();
}
uint8_t bmp_Read_Reg(uint8_t rrrrr)
{
	uint8_t rdata;
	IIC_Start();
	IIC_SendByte(BMPADDRES);
	IIC_ReceiveAck();
	IIC_SendByte(rrrrr);
	IIC_ReceiveAck();

	IIC_Start();
	IIC_SendByte(BMPADDRES | 0x01);
	IIC_ReceiveAck();

	rdata = IIC_ReadByte();
	IIC_SendAck(1);
	IIC_Stop();
	return rdata;
}

void ReadCalibration(void)
{
	uint8_t lsb, msb;
	lsb = bmp_Read_Reg(BMP280_DIG_T1_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_T1_MSB_REG);
	dig_T1 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_T2_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_T2_MSB_REG);
	dig_T2 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_T3_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_T3_MSB_REG);
	dig_T3 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P1_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P1_MSB_REG);
	dig_P1 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P2_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P2_MSB_REG);
	dig_P2 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P3_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P3_MSB_REG);
	dig_P3 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P4_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P4_MSB_REG);
	dig_P4 = (msb << 8) | lsb;	
	lsb = bmp_Read_Reg(BMP280_DIG_P5_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P5_MSB_REG);
	dig_P5 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P6_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P6_MSB_REG);
	dig_P6 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P7_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P7_MSB_REG);
	dig_P7 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P8_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P8_MSB_REG);
	dig_P8 = (msb << 8) | lsb;
	lsb = bmp_Read_Reg(BMP280_DIG_P9_LSB_REG);
	msb = bmp_Read_Reg(BMP280_DIG_P9_MSB_REG);
	dig_P9 = (msb << 8) | lsb;							

}
void bmp_config_Init(void)
{
	bmpIIC_GPIO_Init();
	bmp_write_reg(ctrl_means, 0xFF);//Bit 7, 6, 5 osrs_t[2:0]   Bit 4, 3, 2 osrs_p[2:0]  Bit 1, 0 mode[1:0]
	bmp_write_reg(config, 0x0C);//Bit 7, 6, 5 t_sb[2:0]   Bit 4, 3, 2 filter[2:0]   Bit 0  spi3w_en[0]

	// //ctrl_means 0010 1111
	// //osrs_t 001:001 oversampling ×1  ,osrs_p 011: oversampling ×4  , mode 11: normal mode         
	// bmp_write_reg(ctrl_means, 0x2F);

	// //config 0001 1100
	// //t_sb 000 : 0.5   , filter 111:     spi3w_en 0
	// bmp_write_reg(config, 0x1C);
	ReadCalibration();
}
double bmp_getPress(void)
{
	uint8_t pmsb = bmp_Read_Reg(press_msb);
	uint8_t plsb = bmp_Read_Reg(press_lsb);
	uint8_t pxlsb = bmp_Read_Reg(press_xlsb);
	uint32_t adc_P = ((pmsb << 12) | (plsb << 4) | (pxlsb >> 4));
	return bmp280_compensate_P_int64(adc_P);
}
double bmp_gettemp(void)
{
	uint8_t tmsb = bmp_Read_Reg(temp_msb);
	uint8_t tlsb = bmp_Read_Reg(temp_lsb);
	uint8_t txlsb = bmp_Read_Reg(temp_xlsb);
	uint32_t adc_T = ((tmsb << 12) | (tlsb << 4) | (txlsb >> 4));

	return bmp280_compensate_T_int32(adc_T);
}


//数据手册上面提供的温度补偿函数
#define BMP280_S32_t double
BMP280_S32_t t_fine;
double bmp280_compensate_T_int32(int32_t adc_T)
{
	double var1, var2, temperature;
	var1 = (((double) adc_T) / 16384.0 - ((double) dig_T1) / 1024.0) * ((double) dig_T2);
	var2 = ((((double) adc_T) / 131072.0 - ((double) dig_T1) / 8192.0)  * (((double) adc_T) / 131072.0 - ((double) dig_T1) / 8192.0)) * ((double) dig_T3);
	t_fine = (int32_t) (var1 + var2);
	temperature = (var1 + var2) / 5120.0;

	return temperature;
}

//数据手册上面提供的压力补偿函数
double bmp280_compensate_P_int64(int32_t adc_P)
{
	double var1, var2, pressure;

	var1 = ((double)t_fine / 2.0) - 64000.0;
	var2 = var1 * var1 * ((double) dig_P6) / 32768.0;
	var2 = var2 + var1 * ((double) dig_P5) * 2.0;
	var2 = (var2 / 4.0) + (((double) dig_P4) * 65536.0);
	var1 = (((double) dig_P3) * var1 * var1 / 524288.0  + ((double) dig_P2) * var1) / 524288.0;
	var1 = (1.0 + var1 / 32768.0) * ((double) dig_P1);

	if (var1 == 0.0) {
		return 0; // avoid exception caused by division by zero
	}

	pressure = 1048576.0 - (double) adc_P;
	pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1;
	var1 = ((double) dig_P9) * pressure * pressure / 2147483648.0;
	var2 = pressure * ((double) dig_P8) / 32768.0;
	pressure = pressure + (var1 + var2 + ((double) dig_P7)) / 16.0;

	return pressure;
}
double Altitude_Cal(double pre, double tem)
{
	return ((1 - pow((pre / 1013.25),0.1903)) * 44330.77) / (tem + 273.15);
}
